package com.example.java_gobang.game;

import com.example.java_gobang.JavaGobangApplication;
import com.example.java_gobang.model.GameRequest;
import com.example.java_gobang.model.GameResponse;
import com.example.java_gobang.model.User;
import com.example.java_gobang.model.UserMapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.UUID;


@Data
public class Room {
    //// 使用 UUID 来作为房间 id,UUID 为字符串类型
    private String roomId;
    private User user1;
    private User user2;
    private int whiteUser;


    private  OnlineUserManager onlineUserManager;

    private RoomManager roomManager;

    private UserMapper userMapper;


    public Room() {
        // 构造 Room 的时候生成一个唯一的字符串表示房间 id.
        roomId = UUID.randomUUID().toString();
        onlineUserManager = JavaGobangApplication.context.getBean(OnlineUserManager.class);
        roomManager = JavaGobangApplication.context.getBean(RoomManager.class);
        userMapper = JavaGobangApplication.context.getBean(UserMapper.class);
    }

    public static void main(String[] args) {
        Room room = new Room();
        System.out.println(room.roomId);
    }

    //开始对决操作
    private static final int MAX_ROW = 15;
    private static final int MAX_COL = 15;
    private int[][] board = new int[MAX_ROW][MAX_COL];


    private ObjectMapper objectMapper = new ObjectMapper();


    public void putchess(String payload) throws IOException {
        GameRequest gameRequest = objectMapper.readValue(payload, GameRequest.class);
        GameResponse gameResponse= new GameResponse();

        int chess = gameRequest.getUserId() == user1.getUserId() ? 1 : 2; //chess 为1就说明是用户1下的，为2说明是用户2下的
        int row = gameRequest.getRow();
        int col = gameRequest.getCol();
        if (board[row][col] != 0) {
            System.out.println("当前位置 (" + row + ", " + col + ") 已经有子了!");
            return;
        }
        board[row][col] = chess;//通过 1 和 2标记用户下过的位置，1 是用户1下的，2 是用户2下的


        int winner = checkWinner(row,col,chess); //检查下了一步棋后是否有胜者

        gameResponse.setMessage("putChess");
        gameResponse.setUserId(gameRequest.getUserId());
        gameResponse.setCol(col);
        gameResponse.setRow(row);
        gameResponse.setWinner(winner);





        //要想发送数据，要先获取会话，通过会话可以判断用户是否已经下线，如果已经下线可以直接判断对手获胜
        WebSocketSession user1WebSocketSession = onlineUserManager.getWebSocketSessionByUserIdInGameRoom(user1.getUserId());
        WebSocketSession user2WebSocketSession = onlineUserManager.getWebSocketSessionByUserIdInGameRoom(user2.getUserId());


        if (user1WebSocketSession == null){
            System.out.println("玩家1 掉线!");
            gameResponse.setWinner(user2.getUserId());
        }
        if (user2WebSocketSession == null){
            System.out.println("玩家2 掉线!");
            gameResponse.setWinner(user1.getUserId());
        }

        //发送数据
        String gameResponseJson = objectMapper.writeValueAsString(gameResponse);
        if (user1WebSocketSession != null) {
            user1WebSocketSession.sendMessage(new TextMessage(gameResponseJson));
        }
        if (user2WebSocketSession != null) {
            user2WebSocketSession.sendMessage(new TextMessage(gameResponseJson));
        }

        //如果当前胜负已分, 此时这个房间就失去存在的意义了. 就可以直接销毁房间. (把房间从房间管理器中给移除)
        if (gameResponse.getWinner() != 0) {
            System.out.println("游戏结束! 房间即将销毁! roomId=" + roomId + " 获胜方为: " + gameResponse.getWinner());
            int winUserId = gameResponse.getWinner();
            int loseUserId = gameResponse.getWinner() == user1.getUserId() ? user2.getUserId() : user1.getUserId();
            //执行数据库操作
            userMapper.win(winUserId);
            userMapper.lose(loseUserId);
            roomManager.removeTwoUserBattle(roomManager.getRoomByUserId(user1.getUserId()), user1, user2);
        }


    }

    private int checkWinner(int row, int col, int chess) {
        // 1. 检查所有的行
        //    先遍历这五种情况
        for (int c = col - 4; c <= col; c++) {
            // 针对其中的一种情况, 来判定这五个子是不是连在一起了~
            // 不光是这五个子得连着, 而且还得和玩家落的子是一样~~ (才算是获胜)

            /*
            *   (col - 4, col - 3, col - 2, col - 1, col)
                (col - 3, col - 2, col - 1, col, col + 1)
                (col - 2, col - 1, col, col + 1, col + 2)
                (col - 1, col, col + 1, col + 2, col + 3)
                (col, col + 1, col + 2, col + 3, col + 4)
            * */
            try {
                if (board[row][c] == chess
                        && board[row][c + 1] == chess
                        && board[row][c + 2] == chess
                        && board[row][c + 3] == chess
                        && board[row][c + 4] == chess) {
                    // 构成了五子连珠! 胜负已分!
                    return chess == 1 ? user1.getUserId() : user2.getUserId();
                }
            } catch (ArrayIndexOutOfBoundsException e) {
                // 如果出现数组下标越界的情况, 就在这里直接忽略这个异常.
                continue;
            }
        }

        // 2. 检查所有列
        for (int r = row - 4; r <= row; r++) {
            try {
                if (board[r][col] == chess
                        && board[r + 1][col] == chess
                        && board[r + 2][col] == chess
                        && board[r + 3][col] == chess
                        && board[r + 4][col] == chess) {
                    return chess == 1 ? user1.getUserId() : user2.getUserId();
                }
            } catch (ArrayIndexOutOfBoundsException e) {
                continue;
            }
        }

        // 3. 检查左对角线
        for (int r = row - 4, c = col - 4; r <= row && c <= col; r++, c++) {
            /*
            *   (3, 3), (4, 4), (5, 5), (6, 6), (7, 7)
                (4, 4), (5, 5), (6, 6), (7, 7), (8, 8)
                (5, 5), (6, 6), (7, 7), (8, 8), (9, 9)
                (6, 6), (7, 7), (8, 8), (9, 9), (10, 10)
                (7, 7), (8, 8), (9, 9), (10, 10), (11, 11)
            * */
            try {
                if (board[r][c] == chess
                        && board[r + 1][c + 1] == chess
                        && board[r + 2][c + 2] == chess
                        && board[r + 3][c + 3] == chess
                        && board[r + 4][c + 4] == chess) {
                    return chess == 1 ? user1.getUserId() : user2.getUserId();
                }
            } catch (ArrayIndexOutOfBoundsException e) {
                continue;
            }
        }

        // 4. 检查右对角线
        for (int r = row - 4, c = col + 4; r <= row && c >= col; r++, c--) {
            try {
                if (board[r][c] == chess
                        && board[r + 1][c - 1] == chess
                        && board[r + 2][c - 2] == chess
                        && board[r + 3][c - 3] == chess
                        && board[r + 4][c - 4] == chess) {
                    return chess == 1 ? user1.getUserId() : user2.getUserId();
                }
            } catch (ArrayIndexOutOfBoundsException e) {
                continue;
            }
        }
        // 胜负未分, 就直接返回 0 了.
        return 0;
    }


}
